<template>
    <div class="exam-list">

        <el-dialog title="设置考试时间" :visible.sync="startModalVisible" width="560px" :close-on-click-modal="false">

            <!-- 主体区域 -->
            <el-form label-position="top" label-width="100%">
                <!-- 精确开始时间 -->
                <el-form-item label="精准选择开始时间">
                    <el-date-picker v-model="previewStartTime" type="datetime" placeholder="请选择考试开始时间"
                        style="width: 100%" />
                </el-form-item>

                <!-- 结束时间展示 -->
                <!-- <el-descriptions title="考试时间预览" :column="1" size="small" border>
                    <el-descriptions-item label="开始时间">
                        {{ previewStartTime ? formatDate(previewStartTime) : '未设置' }}
                    </el-descriptions-item>
                    <el-descriptions-item label="预计结束时间">
                        {{ previewEndTime
                            ? formatDate(previewEndTime)
                            : '—' }}
                    </el-descriptions-item>
                </el-descriptions> -->
                <div class="time-preview">
                    <p class="preview-label">考试时间预览</p>
                    <div class="preview-content">
                        <i class="el-icon-time"></i>
                        <span>
                            {{ previewStartTime ? formatDate(previewStartTime) : '未设置' }}
                        </span>
                        <em class="divider">—</em>
                        <span>
                            {{ previewEndTime
                                ? formatDate(previewEndTime)
                                : '—' }} </span>
                    </div>
                </div>

            </el-form>

            <!-- 快捷延迟设置 -->
            <el-card shadow="hover" style="margin-top: 20px;">
                <div style="display: flex; align-items: center; gap: 12px;">
                    <div style="white-space: nowrap; font-weight: bold;">延迟开始：</div>
                    <el-select v-model="delayAmount" placeholder="延迟时长" @change="setDelayedStartTime"
                        style="width: 120px">
                        <el-option v-for="option in currentDelayOptions" :key="option" :label="`${option} ${unitLabel}`"
                            :value="option" />
                    </el-select>
                    <el-select v-model="delayUnit" placeholder="单位" @change="onDelayUnitChange" style="width: 100px;">
                        <el-option label="秒" value="second" />
                        <el-option label="分钟" value="minute" />
                        <el-option label="小时" value="hour" />
                    </el-select>
                </div>
                <div style="margin-top: 8px; color: #888; font-size: 13px;">
                    将自动设置“开始时间”为当前时间 + 延迟时间
                </div>
            </el-card>

            <!-- 底部按钮 -->
            <template #footer>
                <div class="dialog-footer" style="display: flex; justify-content: space-between; align-items: center;">
                    <el-button type="danger" icon="el-icon-lightning" @click="startExamNow" style="font-weight: bold">
                        直接开始
                    </el-button>
                    <div>
                        <el-button @click="cancelStartExam">取消</el-button>
                        <el-button type="primary" @click="confirmStartExam">确定</el-button>
                    </div>
                </div>
            </template>
        </el-dialog>



        <!-- 确认对话框 -->
        <el-dialog title="考试分析确认" :before-close="cancelAnalysis" :visible.sync="confirmAnalysisDialogVisible"
            width="480px" custom-class="analysis-confirm-dialog" :close-on-click-modal="false">
            <div class="dialog-body-content">
                <div class="confirm-icon">
                    <i class="fas fa-chart-pie"></i>
                </div>
                <div class="confirm-text">
                    <h3>请确认生成考试分析报告</h3>
                    <p>
                        即将分析整场考试：<span class="exam-name">{{
                            analysisExam.paperName
                        }}</span>
                    </p>
                    <p class="tip">此操作需要一定时间，请在网络良好时进行</p>
                </div>
            </div>
            <template #footer>
                <div class="dialog-footer">
                    <el-button @click="cancelAnalysis" size="medium">暂不分析</el-button>
                    <el-button type="primary" @click="startAnalysis" size="medium" class="confirm-button">
                        <i class="fas fa-play"></i> 开始分析
                    </el-button>
                </div>
            </template>
        </el-dialog>

        <!-- 考后分析进度提示 -->
        <div v-if="!analysisComplete" class="progress-notification animated-pop">
            <div class="progress-content">
                <i v-if="!(currentProgressMessage == '分析完成！整体报告已生成！')" class="fas fa-spinner fa-spin"></i>
                <i v-else class="fas fa-check-circle" style="color: #4caf50"></i>

                <div class="progress-text">
                    {{ currentProgressMessage }}
                    <span class="dots" v-if="!(currentProgressMessage == '分析完成！整体报告已生成！')">
                        <span class="dot" v-for="n in 3" :key="n" :style="{ animationDelay: n * 0.2 + 's' }">.</span>
                    </span>
                </div>
            </div>
        </div>

        <div v-if="loading" class="loading-state">
            <div class="spinner"></div>
            <p>加载中...</p>
        </div>

        <div v-else-if="filteredExams.length === 0" class="empty-state">
            <div class="empty-illustration">
                <i class="fas fa-calendar-alt"></i>
            </div>
            <h3>暂无考试数据</h3>
            <p>当前没有已发布的考试</p>
        </div>

        <div v-else class="exams-container">
            <div v-for="exam in filteredExams" :key="exam.examId" class="exam-card">
                <div class="exam-header">
                    <h3>{{ exam.paperName }}</h3>
                    <span class="exam-status">
                        <span class="status-dot" :class="getStatusClass(exam)"></span>
                        {{ getStatusText(exam) }}
                    </span>
                </div>
                <div class="exam-meta">
                    <div class="meta-item">
                        <i class="fas fa-clock"></i>
                        <span>考试时长: {{ exam.timeLimit }}分钟</span>
                    </div>
                    <div class="meta-item">
                        <i class="fas fa-star"></i>
                        <span>难度: {{ getDifficultyText(exam.avgDiffculty) }}</span>
                    </div>
                    <div class="meta-item">
                        <i class="fas fa-check-circle"></i>
                        <span>总分: {{ exam.totalScore }}分</span>
                    </div>
                    <div class="meta-item">
                        <i class="fas fa-route"></i>
                        <span>考试地址(点击地址复制)：</span>
                    </div>
                    <div class="meta-item">
                        <el-tooltip class="item" effect="dark" content="点击复制" placement="bottom">
                            <p @click="copyPath(exam.realPaperId)">
                                {{ examPath }}?{{ exam.realPaperId }}
                            </p>
                            <!-- <el-button @click="copyPath(exam.realPaperId)">{{ examPath }}?{{ exam.realPaperId
                                }}</el-button> -->
                        </el-tooltip>
                        <!-- <div class="path-text" >{{ examPath }}?{{ exam.paperId }}</div> -->
                    </div>
                </div>
                <div class="exam-stats">
                    <div class="stat-item">
                        <div class="stat-value">{{ exam.totalExaminees }}</div>
                        <div class="stat-label">总考生</div>
                    </div>
                    <div class="stat-item">
                        <div class="stat-value">{{ exam.inProgress }}</div>
                        <div class="stat-label">进行中</div>
                    </div>
                    <div class="stat-item">
                        <div class="stat-value">{{ exam.completed }}</div>
                        <div class="stat-label">已完成</div>
                    </div>
                </div>

                <div class="exam-actions">
                    <button v-if="exam.status === 0"
                        :class="{ 'btn': true, 'btn-start': true, 'grey': isCountdownPending(exam) }"
                        @click="showStartExamModal(exam)" :disabled="isCountdownPending(exam)">
                        <template v-if="!isCountdownPending(exam)">
                            <i class="fas fa-play"></i> 开始考试
                        </template>
                        <template v-else>
                            距离考试开始还有 {{ showCountdownPending(exam) }}
                        </template>
                    </button>

                    <button v-if="exam.status > 0" class="btn btn-view" @click="showExamDetails(exam)">
                        <i class="fas fa-users"></i> 查看考生
                    </button>

                    <!-- 考后分析按钮 -->
                    <button v-if="exam.status === 2" class="btn btn-analyze" @click="handleAnalyzeClick(exam)"
                        :disabled="analysisInProgress" :class="{
                            disabled: analysisInProgress,
                        }">
                        <i class="fas fa-chart-line"></i> 考后分析
                    </button>

                    <!-- endExam(exam) -->
                    <el-popconfirm v-if="exam.status === 1" icon-color="#EF4444" title="你确定要结束考试吗？"
                        @confirm="endExam(exam)" class="popconfirm-btn">
                        <template v-slot:reference>
                            <button class="btn btn-end">
                                <i class="fas fa-stop-circle"></i> 结束考试
                            </button>
                        </template>
                    </el-popconfirm>
                </div>
            </div>
        </div>

        <!-- 考生信息模态框 -->
        <ExamDetailsModal v-if="showDetailsModal" :exam="selectedExam" :records="examRecords"
            @close="closeDetailsModal" />

        <!-- 考试分析模态框 -->
        <ExamAnalysisModal v-if="showAnalysisModalFlag" :exam="selectedExam" :analysis="analysisExam"
            @close="closeAnalysisModal" ref="examAnalysisModal" />

        <!-- 添加考生模态框 -->
        <AddStudentsModal v-if="showAddStudentsModalFlag" :exam="selectedExam" @close="closeAddStudentsModal"
            @students-added="handleStudentsAdded" />
    </div>
</template>

<script>
import ExamDetailsModal from "../components/exam/ExamDetailsModal.vue";
import ExamAnalysisModal from "../components/exam/ExamAnalysisModal.vue";
import AddStudentsModal from "../components/AddStudentsModal.vue";
// 调用 exam 接口
import {
    getPapersState,
    getAnalysisList,
    getExamRecordList,
    getRecordsByExam,
    updateExam,
    getExamRecordByExamId as getExamRecordByExamIdAPI,
    getTotalAnalysisByExamId,
} from "@/api/exam/index";
import { analysisThisExam as analysisThisExamAPI } from "@/api/exam/index";
import { getBaseURL } from '@/assets/js/config'; // 引入获取基础URL的函数

const baseURL = getBaseURL();

export default {
    name: "ExamList",
    components: {
        ExamDetailsModal,
        ExamAnalysisModal,
        AddStudentsModal,
    },
    data() {
        return {
            exams: [],
            loading: false,
            examPath: `${baseURL}/startExam.html`,
            searchQuery: "",
            showDetailsModal: false,
            showAnalysisModalFlag: false,
            showAddStudentsModalFlag: false,
            countdownDateSeconds: [
                // {
                //   examId: 0,
                //   seconds: 0,
                //   countdownTimer: null, // 用于清除定时器
                // },
            ],
            startModalVisible: false,
            selectedExam: {},
            startTime: null,
            endTime: null,


            // 新增时间模态框选择部分
            delayUnit: 'minute', // 默认单位
            delayAmount: null,
            delayPresets: {
                second: [5, 10, 15, 30, 45],
                minute: [1, 5, 10, 15, 30, 45],
                hour: [1, 2, 3, 6, 12, 24]
            },            // 新增时间模态框选择部分 - 结束

            countdownSeconds: 0,
            countdownTimer: null, // 用于清除定时器
            // 新增的分析状态相关数据
            confirmAnalysisDialogVisible: false,
            analysisInProgress: false,
            analysisComplete: true,
            progressMessages: [],
            analysisTimer: null,
            clickAnalysisExam: null,
            currentAnalysisExamId: null,
            // 只记录当前进度消息
            currentProgressMessage: "",
            //   ellipsis: '',
            //   ellipsisTimer: null,

            nowTimestamp: Date.now(),
            timerId: null,



            examRecords: [
                // {
                //   "recordId": 1,
                //   "userId": 4,
                //   "examId": 1,
                //   "startTime": "2023-06-01T09:00:00",
                //   "endTime": "2023-06-01T09:50:00",
                //   "score": 85,
                //   "status": 0
                // },
                // {
                //   "recordId": 2,
                //   "userId": 5,
                //   "examId": 1,
                //   "startTime": "2023-06-01T09:00:00",
                //   "endTime": "2023-06-01T09:55:00",
                //   "score": 90,
                //   "status": 1
                // },
                // {
                //   "recordId": 3,
                //   "userId": 4,
                //   "examId": 2,
                //   "startTime": "2023-06-15T14:00:00",
                //   "endTime": "2023-06-15T15:20:00",
                //   "score": 70,
                //   "status": 1
                // },
                // {
                //   "recordId": 4,
                //   "userId": 5,
                //   "examId": 2,
                //   "startTime": "2023-06-15T14:00:00",
                //   "endTime": "2023-06-15T15:25:00",
                //   "score": 80,
                //   "status": 1
                // },
                // {
                //   "recordId": 5,
                //   "userId": 4,
                //   "examId": 3,
                //   "startTime": "2023-06-30T09:00:00",
                //   "endTime": null,
                //   "score": null,
                //   "status": 0
                // }
            ],
            analysisExam: {},
        };
    },
    computed: {
        unitLabel() {
            return this.delayUnit === 'second' ? '秒'
                : this.delayUnit === 'hour' ? '小时'
                    : '分钟';
        },
        currentDelayOptions() {
            return this.delayPresets[this.delayUnit];
        },
        filteredExams() {
            if (!this.searchQuery) return this.exams;
            return this.exams.filter((exam) =>
                exam.paperName.toLowerCase().includes(this.searchQuery.toLowerCase())
            );
        },
        previewStartTime: {
            get() {
                if (this.delayAmount) {
                    const ms = this.delayAmount * ({
                        second: 1000,
                        minute: 60 * 1000,
                        hour: 60 * 60 * 1000,
                    })[this.delayUnit];
                    return new Date(this.nowTimestamp + ms);
                }
                return this.startTime ? new Date(this.startTime) : null;
            },
            set(val) {
                this.delayAmount = null;
                this.startTime = val ? val.toISOString() : null;
            }
        },

        // 结束时间：考试时长（假设 examDuration 单位为秒）＋ start
        previewEndTime() {
            const start = this.previewStartTime;
            // 把时长先转换成 Number
            const raw = this.selectedExam.timeLimit;
            const durationMin = Number(raw);

            // 只有当 start 存在，且 duration 能转成合法数字，才返回 Date
            if (!start || isNaN(durationMin)) {
                // 如果时长不对，这里打印一下，方便调试
                if (start && isNaN(durationMin)) {
                    console.warn('[previewEndTime] duration 非法：', raw);
                }
                return null;
            }

            // durationMin 单位是“分钟”，乘以 60*1000 得到毫秒
            const ms = durationMin * 60 * 1000;
            return new Date(start.getTime() + ms);
        }

    },
    created() {
        this.fetchExams();
        this.$registerWebSocketHandler(this.handleMessage);
    },
    mounted() {
        // this.fetchExams();
        this.timerId = setInterval(() => {
            this.nowTimestamp = Date.now();
        }, 1000);
    },
    beforeDestroy() {
        if (this.countdownTimer) clearInterval(this.countdownTimer);
        clearInterval(this.timerId);
    },
    methods: {
        formatDate(time) {
            if (!time) return '';
            return new Date(time).toLocaleString('zh-CN', {
                year: 'numeric',
                month: '2-digit',
                day: '2-digit',
                hour: '2-digit',
                minute: '2-digit',
                second: '2-digit',
                hour12: false
            });
        },
        formatEndTime() {
            return this.endTime ? this.formatDate(this.endTime) : '';
        },
        onDelayUnitChange() {
            this.delayAmount = null;
        },

        setDelayedStartTime() {
            const now = new Date();
            const start = new Date(now);

            if (this.delayUnit === 'second') {
                start.setSeconds(now.getSeconds() + this.delayAmount);
            } else if (this.delayUnit === 'minute') {
                start.setMinutes(now.getMinutes() + this.delayAmount);
            } else if (this.delayUnit === 'hour') {
                start.setHours(now.getHours() + this.delayAmount);
            }

            this.startTime = start;
        },
        startCountdown() {

        },
        handleMessage(message) {
            // console.log("原始消息内容:", message);
            this.currentProgressMessage = "";
            switch (message.messageType) {
                case 103:
                    let res = JSON.parse(message.content);
                    // let analysisData = this.parseAnalysisData(res.data);
                    // this.analysisExam.unshift(analysisData);
                    // this.analysisComplete = true
                    this.currentProgressMessage = res.msg;
                    this.analysisInProgress = false;
                    setTimeout(() => {
                        this.analysisComplete = true;
                    }, 1000);
                    break;
                case 10000:
                    // 刷新页面
                    this.fetchExams();
                    break;
                case 101:
                case 10201:
                case 10202:
                case 10203:
                case 10204:
                case 10205:
                case 10206:
                case 10207:
                case 10208:
                case 10209:
                case 10210:
                case 10211:
                    this.analysisComplete = false;
                    this.currentProgressMessage = JSON.parse(message.content).msg;
                    break;
                default:
            }
        },
        // 接收到的websocket消息进行解析并赋值
        parseAnalysisData(data) {
            try {
                const parsedData = typeof data === "string" ? JSON.parse(data) : data;

                // 解析嵌套的 JSON 字符串字段
                parsedData.questionTypeAccuracy = JSON.parse(
                    parsedData.questionTypeAccuracy
                );

                parsedData.knowledgePointAccuracy = JSON.parse(
                    parsedData.knowledgePointAccuracy
                );

                parsedData.insightfulStudents = JSON.parse(parsedData.insightfulStudents);

                parsedData.outstandingStudents = JSON.parse(parsedData.outstandingStudents);

                parsedData.highRiskKnowledgePoints = JSON.parse(
                    parsedData.highRiskKnowledgePoints
                );

                parsedData.sharedWeakPoints = JSON.parse(parsedData.sharedWeakPoints);

                parsedData.allWeakPoints = JSON.parse(parsedData.allWeakPoints);

                parsedData.needsAttentionStudents = JSON.parse(
                    parsedData.needsAttentionStudents
                );

                return parsedData;
            } catch (error) {
                console.error("解析分析数据失败:", error);
                return null;
            }
        },
        // 复制考试地址到剪贴板
        copyPath(examId) {
            const path = `${this.examPath}?${examId}`;
            if (!navigator.clipboard) {
                return this.fallbackCopyText(path); // 使用备用方案
            }
            navigator.clipboard
                .writeText(path)
                .then(() => {
                    this.$message.success("考试地址已复制到剪贴板");
                })
                .catch((err) => {
                    // console.error('复制失败:', err);
                    return this.fallbackCopyText(path); // 使用备用方案
                });
        },
        fallbackCopyText(text) {
            const textarea = document.createElement("textarea");
            textarea.value = text;
            textarea.style.position = "fixed"; // 避免滚动到底部
            document.body.appendChild(textarea);
            textarea.select();

            try {
                const successful = document.execCommand("copy");
                this.$message.success(successful ? "复制成功" : "复制失败，请手动复制");
            } catch (err) {
                this.$message.error("请手动选择文本后复制");
            } finally {
                document.body.removeChild(textarea);
            }
        },
        async fetchExams() {
            this.loading = true;
            try {

                let params = {
                    page: 1,
                    pageSize: 999
                }
                const res = await getPapersState(params);


                let { data } = res.data;

                this.exams = data.rows;

                // 循环当前 exams 数组，添加倒计时
                this.exams.forEach((exam) => {
                    this.addCountdownPending(exam);
                });

            } catch (error) {
                // console.error('获取考试数据失败:', error);
            } finally {
                this.loading = false;
            }
        },
        async fetchExamRecord() {
            this.loading = true;
            try {
                let page = {
                    page: 1,
                    pageSize: 999,
                };
                const examRecords = await getExamRecordList(page);

                this.examRecords = examRecords.data.data.rows;
            } catch (error) {
                // console.error('获取考试数据失败:', error);
            } finally {
                this.loading = false;
            }
        },
        async fetchExamAnalysis() {
            this.loading = true;
            try {
                let page = {
                    page: 1,
                    pageSize: 999,
                };
                const examAnalysis = await getAnalysisList(page);
                this.examAnalysis = examAnalysis.data.data.rows;
            } catch (error) {
                console.error("获取考试数据失败:", error);
            } finally {
                this.loading = false;
            }
        },

        showStartExamModal(exam) {
            this.selectedExam = exam;
            // console.log("Selected Exam:", this.selectedExam);

            this.startTime = null;
            this.endTime = null;
            this.startModalVisible = true;
        },
        cancelStartExam() {
            this.startModalVisible = false;
        },

        // 时间格式化函数
        formatToLocalISOString(date) {
            const pad = (n) => n.toString().padStart(2, "0");
            const YYYY = date.getFullYear();
            const MM = pad(date.getMonth() + 1);
            const DD = pad(date.getDate());
            const hh = pad(date.getHours());
            const mm = pad(date.getMinutes());
            const ss = pad(date.getSeconds());
            return `${YYYY}-${MM}-${DD}T${hh}:${mm}:${ss}`;
        },

        async confirmStartExam() {
            if (!this.startTime || !this.endTime) {
                this.$message.warning("请选择开始和结束时间！");
                return;
            }

            const now = new Date();
            // 兜底：无论用户怎么操作，都以最新的 computed 值为准
            const start = this.previewStartTime;
            const end = this.previewEndTime;

            const timeDiffInSeconds = Math.floor(
                (start.getTime() - now.getTime()) / 1000
            );

            // 校验：开始时间至少晚于当前时间 1 分钟
            if (timeDiffInSeconds < 10) {
                this.$message.warning("开始时间至少要晚于当前时间 10 秒！");
                return;
            }

            // 兜底：结束时间必须晚于开始时间
            if (end <= start) {
                this.$message.warning("结束时间必须晚于开始时间！");
                return;
            }

            const exam_ = {
                examId: this.selectedExam.examId,
                status: 0,
                startTime: this.formatToLocalISOString(start),
                endTime: this.formatToLocalISOString(end),
            };

            try {
                let res = await updateExam(exam_);
                this.$message.success("考试开始已成功设置！", res);
            } catch (e) {
                this.$message.error("设置考试失败", e);
            }

            // this.previewEndTime = null;
            this.delayAmount = null
            this.startModalVisible = false;

            this.fetchExams();
        },
        isCountdownPending(exam) {
            // 检查是否有显示倒计时
            if (!(exam.startTime && exam.endTime)) return false;

            // 获取当前时间和考试的开始时间
            const now = new Date();
            const start = new Date(exam.startTime);
            if (now < start) {
                return true; // 如果当前时间小于开始时间，返回 true
            }

            return false;
        },
        // 显示倒计时时间的方法
        showCountdownPending(exam) {
            for (let i = 0; i < this.countdownDateSeconds.length; i++) {
                if (this.countdownDateSeconds[i].examId === exam.examId) {
                    // 如果当前剩余时间大于一分钟就按照多少分钟多少秒来显示，大于1小时就按照多少小时多少分钟多少秒来显示
                    if (this.countdownDateSeconds[i].seconds >= 3600) {
                        const hours = Math.floor(this.countdownDateSeconds[i].seconds / 3600);
                        const minutes = Math.floor((this.countdownDateSeconds[i].seconds % 3600) / 60);
                        const seconds = this.countdownDateSeconds[i].seconds % 60;
                        return `${hours}小时${minutes}分钟${seconds}秒`;
                    } else if (this.countdownDateSeconds[i].seconds >= 60) {
                        const minutes = Math.floor(this.countdownDateSeconds[i].seconds / 60);
                        const seconds = this.countdownDateSeconds[i].seconds % 60;
                        return `${minutes}分钟${seconds}秒`;
                    }
                    // 否则直接返回秒数
                    return `${this.countdownDateSeconds[i].seconds} 秒`;
                }
            }
        },
        // 判断是否开启倒计时
        addCountdownPending(exam) {
            // 获取当前考试的开始时间，和结束时间，如果不为null就返回true，否则返回false

            if (!(exam.startTime && exam.endTime)) return false;

            // 如果考试的开始时间和结束时间都存在，且当前时间小于开始时间，则返回true
            const now = new Date();
            const start = new Date(exam.startTime);
            const end = new Date(exam.endTime);

            // console.log("当前时间:", now, "开始时间:", start, "结束时间:", end);

            if (now < start) {
                // 为每张试卷添加一个专用的定时器来进行倒计时
                if (!this.countdownDateSeconds.some((c) => c.examId === exam.examId)) {
                    // 如果当前考试的倒计时不存在，则添加到数组中
                    this.countdownDateSeconds.push({
                        examId: exam.examId,
                        seconds: Math.floor((start.getTime() - now.getTime()) / 1000),
                        countdownTimer: setInterval(() => {
                            // 开启定时器，并获得当前数组的位置
                            const index = this.countdownDateSeconds.findIndex(
                                (c) => c.examId === exam.examId
                            );
                            if (index !== -1) {
                                this.countdownDateSeconds[index].seconds -= 1;
                                if (this.countdownDateSeconds[index].seconds < 0) {
                                    // 清除当前的定时器，并从数组中移除当前的倒计时
                                    clearInterval(this.countdownDateSeconds[index].countdownTimer);
                                    this.countdownDateSeconds.splice(index, 1);
                                    // 延迟一秒钟刷新页面
                                }
                            }
                        }, 1000),
                    });
                }
                return true;
            }
        },
        async getExamAnalysis(exam) {
            let param = {
                examId: exam.examId,
                page: 1,
                pageSize: 999,
            };
            let res = await getRecordsByExam(param);
            let { rows } = res.data.data;

            const recordIds = rows.map((r) => r.recordId);
            this.analysisExam =
                this?.examAnalysis?.filter((a) => recordIds.includes(a.recordId)) || [];
        },

        async showExamDetails(exam) {
            this.selectedExam = exam;
            try {
                let param = {
                    examId: exam.examId,
                    page: 1,
                    pageSize: 999,
                };
                let res = await getRecordsByExam(param);
                let { data } = res.data;

                this.examRecords = data.rows;
            } catch (error) {
                // console.error('获取考试数据失败:', error);
                this.$message.error("获取考试数据失败");
            } finally {
                this.loading = false;
            }

            this.showDetailsModal = true;
        },

        closeDetailsModal() {
            this.showDetailsModal = false;
        },
        refreshExams() {
            // 清理旧定时器
            this.countdownDateSeconds.forEach(item => {
                clearInterval(item.countdownTimer);
            });
            this.countdownDateSeconds = [];

            // 获取试卷集合后重新调用 addCountdownPending
            this.fetchExams();
        },

        closeAnalysisModal() {
            this.showAnalysisModalFlag = false;
        },

        closeAddStudentsModal() {
            this.showAddStudentsModalFlag = false;
        },

        handleStudentsAdded({ examId, studentIds }) {
            const examIndex = this.exams.findIndex((e) => e.paperId === examId);
            if (examIndex !== -1) {
                this.exams[examIndex].totalExaminees += studentIds.length;
            }
        },
        async startExamNow() {
            const now = new Date();

            // 结束时间
            const end = new Date(now.getTime() + this.selectedExam.timeLimit * 60000);


            const exam_ = {
                examId: this.selectedExam.examId,
                status: 1,
                startTime: null, // 直接开始不需要时间
                endTime: this.formatToLocalISOString(end),
            };
            try {
                let res = await updateExam(exam_);
                this.$message.success("考试已经开始！", res);
            } catch (e) {
                this.$message.error("立即开始失败！", e);
            }
            this.startModalVisible = false;
            this.fetchExams();
        },

        async endExam(exam) {
            // 更新考试状态为已完成
            let exam_ = {
                examId: exam.examId,
                status: 2,
            };
            let res;
            try {
                res = await updateExam(exam_);
            } catch (e) {
                this.$message.error("结束考试失败");
            }
            this.fetchExams();
        },

        getDifficultyText(level) {
            const levels = [
                "容易",
                "容易",
                "容易",
                "中等",
                "中等",
                "中等",
                "中等",
                "困难",
                "困难",
                "困难",
            ];
            return levels[level - 1] || "未知";
        },

        getStatusText(exam) {
            if (exam.status === 1) return "进行中";
            if (exam.status === 2) return "已完成";
            return "未开始";
        },

        getStatusClass(exam) {
            if (exam.status === 1) return "in-progress";
            if (exam.status === 2) return "completed";
            return "not-started";
        },
        async handleAnalyzeClick(exam) {
            this.selectedExam = exam;
            // 数据库请求
            // 检查当前考试是否已完成分析
            // 1. 获取分析记录
            // 2. 没有就走确认对话框流程, 打websokcet请求
            // 3. 有就直接 打开分析记录
            this.analysisInProgress = true;
            try {
                let res = await getTotalAnalysisByExamId({ examId: exam.examId });
                // 防止静默处理报错
                if (res != "") {
                    let { data } = res.data;
                    // 没有则走 [进度] 流程
                    this.selectedExam = exam;
                    if (data == null) {
                        this.initiateAnalysis(exam);
                    } else {
                        this.showAnalysisModalFlag = true;
                        this.analysisInProgress = false;
                        let analysisData = this.parseAnalysisData(data);
                        this.analysisExam = analysisData;
                    }
                }

            } catch (err) {
                this.$message.error("获取考试分析数据失败");
            }
        },
        initiateAnalysis(exam) {
            // todo: 在这里发起请求, 如果已存在分析结果, 则直接打开
            this.clickAnalysisExam = exam;
            this.confirmAnalysisDialogVisible = true; // 打开对话框
        },

        cancelAnalysis() {
            this.confirmAnalysisDialogVisible = false;
            this.clickAnalysisExam = null;
            this.analysisInProgress = false;
        },

        // 对话框 点击了 确认
        async startAnalysis() {
            this.confirmAnalysisDialogVisible = false;
            this.currentAnalysisExamId = this.clickAnalysisExam.paperId;

            const response = await analysisThisExamAPI({
                examId: this.selectedExam.examId,
            });
        },
    },
    watch: {
        startTime(newVal) {
            if (newVal && this.selectedExam?.timeLimit) {
                const start = new Date(newVal);
                const end = new Date(
                    start.getTime() + this.selectedExam.timeLimit * 60000
                );
                this.endTime = end;
            } else {
                this.endTime = null;
            }
        },
    },
};
</script>

<style lang="less" scoped>
@primary: #4361ee;
@primary-light: #a5b4fc;
@primary-lighter: #e0e7ff;
@secondary: #3a0ca3;
@success: #10b981;
@warning: #f59e0b;
@danger: #ef4444;
@gray-50: #f9fafb; // 添加这一行
@gray-100: #f3f4f6;
@gray-200: #e5e7eb;
@gray-300: #d1d5db;
@gray-400: #9ca3af;
@gray-500: #6b7280;
@gray-600: #4b5563;
@gray-700: #374151;
@gray-800: #1f2937;
@gray-900: #111827;

@shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
@shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
@shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
@radius-sm: 0.375rem;
@radius-md: 0.5rem;
@radius-lg: 0.75rem;
@transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);

.exam-list {
    flex: 1;
    padding: 2rem;
    background-color: @gray-100;
    overflow-y: auto;

    .panel-header {
        display: flex;
        flex-direction: column;
        gap: 1.5rem;
        margin-bottom: 2rem;

        .header-content {
            .panel-title {
                margin: 0;
                font-size: 1.75rem;
                font-weight: 700;
                color: @gray-900;
                position: relative;
                padding-left: 1rem;

                &::before {
                    content: "";
                    position: absolute;
                    left: 0;
                    top: 0;
                    bottom: 0;
                    width: 4px;
                    background: linear-gradient(to bottom, @primary, @secondary);
                    border-radius: 2px;
                }
            }

            .panel-subtitle {
                margin: 0.5rem 0 0;
                font-size: 0.9375rem;
                color: @gray-500;
            }
        }

        .action-buttons {
            display: flex;
            gap: 1rem;
            align-items: center;

            .search-box {
                flex: 1;
                max-width: 400px;
                position: relative;
                transition: @transition;

                i {
                    position: absolute;
                    left: 1rem;
                    top: 50%;
                    transform: translateY(-50%);
                    color: @gray-400;
                    transition: @transition;
                }

                input {
                    width: 100%;
                    padding: 0.75rem 1rem 0.75rem 2.5rem;
                    border: 1px solid @gray-300;
                    border-radius: @radius-md;
                    font-size: 0.9375rem;
                    transition: @transition;
                    background-color: white;

                    &:focus {
                        outline: none;
                        border-color: @primary;
                        box-shadow: 0 0 0 3px rgba(@primary, 0.1);

                        +i {
                            color: @primary;
                        }
                    }

                    &::placeholder {
                        color: @gray-400;
                    }
                }
            }
        }
    }

    .loading-state {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        height: 300px;
        gap: 1rem;

        .spinner {
            width: 40px;
            height: 40px;
            border: 4px solid rgba(@primary, 0.1);
            border-top-color: @primary;
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }

        p {
            margin: 0;
            color: @gray-600;
        }
    }

    .empty-state {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        height: 400px;
        text-align: center;
        gap: 1rem;

        .empty-illustration {
            width: 80px;
            height: 80px;
            display: flex;
            align-items: center;
            justify-content: center;
            color: @primary-light;
            font-size: 3rem;
            margin-bottom: 1rem;
        }

        h3 {
            margin: 0;
            color: @gray-800;
            font-size: 1.25rem;
        }

        p {
            margin: 0;
            color: @gray-500;
            max-width: 300px;
        }
    }

    .exams-container {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
        gap: 1.5rem;
    }

    .exam-card {
        background: white;
        border-radius: @radius-md;
        padding: 1.5rem;
        box-shadow: @shadow-sm;
        transition: @transition;
        border: 1px solid @gray-200;
        display: flex;
        flex-direction: column;
        height: 100%;

        &:hover {
            transform: translateY(-2px);
            box-shadow: @shadow-md;
            border-color: @primary-light;
        }

        .exam-header {
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
            margin-bottom: 1rem;

            h3 {
                margin: 0;
                font-size: 1.125rem;
                color: @gray-800;
                flex: 1;
            }

            .exam-status {
                font-size: 0.875rem;
                display: flex;
                align-items: center;
                gap: 0.5rem;
                white-space: nowrap;

                .status-dot {
                    width: 8px;
                    height: 8px;
                    border-radius: 50%;
                    display: inline-block;

                    &.in-progress {
                        background-color: @warning;
                    }

                    &.completed {
                        background-color: @success;
                    }

                    &.not-started {
                        background-color: @gray-400;
                    }
                }
            }
        }

        .exam-meta {
            display: flex;
            flex-direction: column;
            gap: 0.75rem;
            margin-bottom: 1.25rem;

            .meta-item {
                display: flex;
                align-items: center;
                gap: 0.5rem;
                font-size: 0.875rem;
                color: @gray-600;

                // .path-text {
                //   text-align: center;
                //   width: 100%;
                //   background: #eaeaea;
                //   border-radius: 5px 5px 5px 5px;
                //   border: 2px solid #00000063;
                //   cursor: pointer;
                //   transition: all 0.3s ease;
                //   &:hover {
                //     background: #dbdbdb;
                //   }
                // }
                .el-button.el-tooltip.item.el-button--default {
                    width: 100%;
                }

                i {
                    color: @gray-500;
                    width: 16px;
                    text-align: center;
                }
            }
        }

        .exam-stats {
            display: flex;
            gap: 1.5rem;
            margin: 1.5rem 0;
            padding: 1rem 0;
            border-top: 1px solid @gray-100;
            border-bottom: 1px solid @gray-100;

            .stat-item {
                text-align: center;
                flex: 1;

                .stat-value {
                    font-size: 1.25rem;
                    font-weight: 600;
                    color: @primary;
                }

                .stat-label {
                    font-size: 0.75rem;
                    color: @gray-500;
                    margin-top: 0.25rem;
                }
            }
        }

        .exam-actions {
            display: flex;
            gap: 0.75rem;
            margin-top: auto;

            // .el-popconfirm{
            //    background-color: yellow;
            // }
            // background-color: #EF4444;


            .popconfirm-btn {
                flex: 1;

                // 插槽内 button 也撑满
                .btn {
                    width: 100%;
                }
            }

            .btn {
                flex: 1;
                padding: 0.625rem 0.75rem;
                border-radius: @radius-sm;
                font-size: 0.875rem;
                font-weight: 500;
                display: flex;
                align-items: center;
                justify-content: center;
                gap: 0.5rem;
                cursor: pointer;
                transition: @transition;
                border: none;

                &.btn-end {
                    background-color: @danger;
                    color: white;

                    &:hover {
                        background-color: darken(@danger, 10%);
                    }
                }

                i {
                    font-size: 0.875rem;
                }

                &.btn-add {
                    background-color: @success;
                    color: white;

                    &:hover {
                        background-color: darken(@success, 5%);
                    }
                }

                &.btn-start {
                    background-color: @primary;
                    color: white;

                    &:hover {
                        background-color: darken(@primary, 5%);
                    }
                }

                &.grey {
                    background: rgba(16, 185, 129, 0.1);
                    color: #10B981;

                    &:hover {
                        background: rgba(16, 185, 129, 0.2);
                    }
                }

                &.btn-view {
                    background-color: @primary-lighter;
                    color: @primary;

                    &:hover {
                        background-color: darken(@primary-lighter, 5%);
                    }
                }

                &.btn-analyze {
                    background-color: @primary;
                    color: white;

                    &:hover {
                        background-color: darken(@primary, 5%);
                    }

                    &.disabled {
                        background-color: @gray-300;
                        color: @gray-600;
                        cursor: not-allowed;
                        opacity: 0.7;
                    }
                }
            }

        }
    }
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

@media (max-width: 768px) {
    .exam-list {
        padding: 1.5rem;
    }
}

@media (max-width: 480px) {
    .exam-list {
        padding: 1rem;

        .exams-container {
            grid-template-columns: 1fr;
        }
    }
}

.start-exam-dialog .el-dialog__header {
    border-bottom: 1px solid #ebeef5;
    padding-top: 0px;
}

.start-exam-dialog .el-dialog__footer {
    border-top: 1px solid #ebeef5;
    padding-top: 10px;
}

/* 简约风格的确认对话框 */
.analysis-confirm-dialog {
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
    border: 1px solid #e8e8e8;

    .el-dialog__header {
        background: #f9fafb;
        border-bottom: 1px solid #e8e8e8;
        padding: 20px;

        .el-dialog__title {
            color: #2c3e50;
            font-weight: 600;
            font-size: 18px;
        }

        .el-dialog__headerbtn {
            top: 22px;
        }
    }

    .dialog-body-content {
        display: flex;
        align-items: center;
        padding: 25px;

        .confirm-icon {
            width: 60px;
            height: 60px;
            background: #f0f7ff;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            margin-right: 20px;

            i {
                font-size: 28px;
                color: #3498db;
            }
        }

        .confirm-text {
            h3 {
                color: #2c3e50;
                margin-bottom: 8px;
                font-weight: 600;
                font-size: 16px;
            }

            p {
                color: #555;
                margin: 5px 0;
                font-size: 14px;
            }

            .exam-name {
                font-weight: 600;
                color: #3498db;
            }

            .tip {
                font-size: 13px;
                color: #95a5a6;
                margin-top: 8px;
            }
        }
    }

    .dialog-footer {
        padding: 15px 20px;
        background: #f9fafb;
        border-top: 1px solid #eee;
        text-align: right;

        .confirm-button {
            background: #3498db;
            border-color: #3498db;
            color: white;
        }
    }
}

/* 进度提示 */
.progress-notification {
    position: fixed;
    top: 70px;
    right: 20px;
    z-index: 2000;
    width: 350px;
    background: white;
    border-radius: 10px;
    box-shadow: 0 5px 20px rgba(0, 0, 0, 0.12);
    border-left: 4px solid #3498db;
    overflow: hidden;
    animation: slideIn 0.5s ease-out;

    .progress-content {
        padding: 20px;
        display: flex;
        align-items: center;

        i {
            font-size: 24px;
            margin-right: 15px;
            flex-shrink: 0;
        }

        .progress-text {
            flex-grow: 1;
            font-size: 15px;
            color: #2c3e50;
            line-height: 1.5;
            display: flex;
            align-items: center;

            .dots {
                margin-left: 5px;
                letter-spacing: 2px;
                font-weight: bold;
                font-size: 20px;
                color: #3498db;
                display: inline-block;
                min-width: 30px;
                transition: all 0.3s ease;
            }
        }
    }
}

/* 分析完成时的特殊样式 */
.progress-notification .fa-check-circle {
    color: #4caf50 !important;
}

@keyframes slideIn {
    0% {
        transform: translateX(100%);
        opacity: 0;
    }

    100% {
        transform: translateX(0);
        opacity: 1;
    }
}

.dots {
    display: inline-flex;
    margin-left: 6px;
    align-items: baseline;
    min-width: 30px;

    .dot {
        font-weight: bold;
        font-size: 20px;
        color: #3498db;
        opacity: 0;
        animation: dot-blink 1.2s infinite ease-in-out;
        padding: 0 1px;
    }
}

@keyframes dot-blink {
    0% {
        opacity: 0;
        transform: scale(0.7);
    }

    50% {
        opacity: 1;
        transform: scale(1.1);
    }

    100% {
        opacity: 0;
        transform: scale(0.7);
    }
}




.time-preview {
    background: rgba(255, 255, 255, 0.85);
    backdrop-filter: blur(12px);
    border: 1px solid rgba(160, 160, 160, 0.3);
    border-radius: 14px;
    padding: 18px 24px;
    margin-bottom: 24px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06);
}

.time-preview .preview-label {
    margin-top: -6px;
    font-size: 13px;
    font-weight: 500;
    color: #909399;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    margin-bottom: 12px;
}

.time-preview .preview-content {
    margin-top: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: "PingFang SC", "Helvetica Neue", sans-serif;
    font-size: 17px;
    font-weight: 600;
    color: #303133;
}

.time-preview .preview-content .el-icon-time {
    font-size: 20px;
    margin-right: 8px;
    color: #409EFF;
    animation: pulse 2s infinite;
}

.time-preview .preview-content .divider {
    margin: 0 12px;
    font-style: normal;
    color: #C0C4CC;
    font-weight: 300;
}

@keyframes pulse {

    0%,
    100% {
        opacity: 1;
        transform: scale(1);
    }

    50% {
        opacity: 0.6;
        transform: scale(1.1);
    }
}
</style>
